package ED;

import net.datastructures.Edge;
import net.datastructures.Graph;
import net.datastructures.InvalidPositionException;
import net.datastructures.NodePositionList;
import net.datastructures.PositionList;
import net.datastructures.Vertex;

/**
 * Implementacion de un grafo no direccionado con una lista de Aristas y una lista de vertices 
 * 
 * @author Sebastian Giulietti 69032 
 * @author Adrian Sanchez 64251
 *
 * @param <E> Tipo de dato de los vertices
 * @param <M> Tipo de dato de las aristas
 */
public class GraphImp<E, M> implements Graph<E, M> {

	PositionList<Edge<M>> listaEdges;
	PositionList<Vertex<E>> listaVertices;

	public GraphImp() {
		listaVertices = new NodePositionList<Vertex<E>>();
		listaEdges = new NodePositionList<Edge<M>>();

	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean areAdjacent(Vertex<E> u, Vertex<E> v)
			throws InvalidPositionException {

		MyVertex<E, M> myVertexU = (MyVertex<E, M>) u;

		for (Edge<M> e : myVertexU.adjacencyList) {
			if (opposite(u, e) == v)
				return true;
		}

		return false;
	}

	@Override
	public Iterable<Edge<M>> edges() {
		return listaEdges;
	}

	@Override
	public Vertex<E>[] endVertices(Edge<M> e) throws InvalidPositionException {
		// TODO Auto-generated method stub
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Iterable<Edge<M>> incidentEdges(Vertex<E> v)
			throws InvalidPositionException {
		MyVertex<E, M> vv = (MyVertex<E, M>) v;
		return vv.getAdjacencyList();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Edge<M> insertEdge(Vertex<E> u, Vertex<E> v, M o)
			throws InvalidPositionException {

		if (!areAdjacent(u, v)) {
			MyEdge<E, M> myEdge = new MyEdge<E, M>();
			myEdge.setOrigen(u);
			myEdge.setDestino(v);
			myEdge.addRotulo(o);

			listaEdges.addLast(myEdge);
			myEdge.setPosition(listaEdges.last());

			((MyVertex<E, M>) u).addEdge(myEdge);
			((MyVertex<E, M>) v).addEdge(myEdge);

			return myEdge;
		} else
			return null;
	}

	@Override
	public MyVertex<E, M> insertVertex(E o) {

		MyVertex<E, M> myVertex = new MyVertex<E, M>();
		myVertex.addCelda(o);
		listaVertices.addLast(myVertex);
		myVertex.addPosition(listaVertices.last());

		return myVertex;
	}

	@Override
	public int numEdges() {
		return listaEdges.size();
	}

	@Override
	public int numVertices() {
		return listaVertices.size();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Vertex<E> opposite(Vertex<E> v, Edge<M> e)
			throws InvalidPositionException {

		MyVertex<E, M> myVertex = (MyVertex<E, M>) v;
		MyEdge<E, M> myEdge = (MyEdge<E, M>) e;

		if (myEdge.getOrigen() == myVertex)
			return myEdge.getDestino();
		return myEdge.getOrigen();

	}

	@SuppressWarnings("unchecked")
	@Override
	public M removeEdge(Edge<M> e) throws InvalidPositionException {

		MyEdge<E, M> myEdge = (MyEdge<E, M>) e;

		MyVertex<E, M> myVertexO = (MyVertex<E, M>) myEdge.getOrigen();
		MyVertex<E, M> myVertexD = (MyVertex<E, M>) myEdge.getOrigen();

		myVertexO.adjacencyList.remove(myEdge.getPosition());
		myVertexD.adjacencyList.remove(myEdge.getPosition());

		return null;
	}

	@Override
	public E removeVertex(Vertex<E> v) throws InvalidPositionException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public M replace(Edge<M> p, M o) throws InvalidPositionException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public E replace(Vertex<E> p, E o) throws InvalidPositionException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Iterable<Vertex<E>> vertices() {
		PositionList<Vertex<E>> a = listaVertices;
		return a;
	}

}
